package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.apis.schedule.IScheduleClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.schedule.dto.Task;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.utils.ProtostuffUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.thread.WmUserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import springfox.documentation.spring.web.json.Json;

import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private AutoScanService autoScanService;

    @Autowired
    private IArticleClient iArticleClient;

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;



    @Override
    public ResponseResult getAllNews(WmNewsPageReqDto dto) {

        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        Short status = dto.getStatus();
        Date beginPubDate = dto.getBeginPubDate();
        Date endPubDate = dto.getEndPubDate();
        Integer channelId = dto.getChannelId();
        String keyword = dto.getKeyword();
        Integer userId = WmUserThreadLocal.get().getId();

        //构建分页构造器
        Page<WmNews> page = new Page<>(dto.getPage(), dto.getSize());

        //构建查询条件
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        //判断状态
        wrapper.eq(status != null,WmNews::getStatus,status);
        //时间范围
        wrapper.between(beginPubDate != null && endPubDate != null,WmNews::getPublishTime,beginPubDate,endPubDate);
        //查询频道
        wrapper.eq(channelId != null,WmNews::getChannelId,channelId);
        //模糊查询关键字
        wrapper.like(StringUtils.isNotEmpty(keyword),WmNews::getTitle,keyword);
        //判断是否为当前用户
        wrapper.eq(WmNews::getUserId,userId);
        //排序
        wrapper.orderByDesc(WmNews::getCreatedTime);

        page = wmNewsMapper.selectPage(page,wrapper);

        //组装返回值
        PageResponseResult pageResponseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
        pageResponseResult.setData(page.getRecords());

        return pageResponseResult;
    }

    @Autowired
    private IScheduleClient scheduleClient;
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult submit(WmNewsDto dto) {

        //1.提取新闻内容
        WmNews wmNews = getWmNews(dto);

        //2.插入新闻表
        int newsResult = wmNewsMapper.insert(wmNews);
        if (newsResult < 1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }

        //3.判断是否为草稿
        if (dto.getStatus() == 0){
            log.info("文章为草稿,没有添加素材 ");
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }

        //4.提取新闻图片
        //4.1提取内容图
        List<String> contentImages = getContentImages(dto.getContent());
        //4.2提取封面图
        List<String> coverImages = new ArrayList<>();

        //7.自动布局
        if (dto.getType() == -1){
            List<String> list = autoLayout(contentImages);
            //更新一下news表,布局方式改掉
            Integer coverImageSize = list.size();
            wmNews.setType(coverImageSize.shortValue());
            wmNewsMapper.updateById(wmNews);
        }else {
            coverImages = dto.getImages();
        }

        //5.插入内容图
        addMaterial(contentImages,1,wmNews.getId());

        //6.插入封面图
        addMaterial(coverImages,0,wmNews.getId());


        //8.调用审核代码
//        try {
//            autoScanService.autoScanWmNews(wmNews.getId().longValue());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        Boolean addTaskResult = addToTask(wmNews.getId(), wmNews.getPublishTime().getTime());
        if (!addTaskResult){
            throw new RuntimeException("任务添加失败");
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Override
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        if (wmNewsDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        Integer newsId = wmNewsDto.getId();
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        if (wmNews==null){
            log.warn("新闻不存在");
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"新闻不存在");
        }

        Short status = wmNews.getStatus();
        if (9!=status){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"新闻未发布");
        }
        //修改状态并更新
        wmNews.setEnable(wmNewsDto.getEnable());
        int updateResult = wmNewsMapper.updateById(wmNews);
        if (updateResult<1){
            log.warn("新闻更新失败");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"新闻更新失败");
        }

        Map<String, Object> map = new HashMap<>();
        map.put("articleId", wmNews.getArticleId());
        map.put("enable", wmNews.getEnable());
        kafkaTemplate.send("new.up.or.down", JSON.toJSONString(map));



        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult passOrFail(NewsAuthDto dto, Integer type) {
        if (dto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        Integer id = dto.getId();
        String msg = dto.getMsg();
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "新闻不存在");
        }

        int status = type == 1 ? 9 : 2;
        wmNews.setStatus((short) status);
        wmNews.setReason(type==1?"通过":msg);
        int updateResult = wmNewsMapper.updateById(wmNews);
        if (updateResult<1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "新闻审核失败");
        }

        if (type==1){
            ArticleDto articleDto = autoScanService.wmNews2ArticleDto(wmNews);
            ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
            if (responseResult ==null||responseResult.getCode() != 200){
                throw new RuntimeException("文章保存失败");
            }
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult findList(NewsAuthDto dto) {
        //1.参数检查
        dto.checkParam();

        //记录当前页
        int currentPage = dto.getPage();

        //2.分页查询+count查询
//        dto.setPage((dto.getPage()-1)*dto.getSize());
//        List<WmNewsVo> wmNewsVoList = wmNewsMapper.findListAndPage(dto);
//        int count = wmNewsMapper.findListCount(dto);

        Page<WmNews> page = new Page<>();
        Page<WmNews> pageResult = wmNewsMapper.selectPage(page, null);

        //3.结果返回
        Long total = pageResult.getTotal();
        ResponseResult responseResult = new PageResponseResult(currentPage,dto.getSize(),total.intValue());
        responseResult.setData(pageResult.getRecords());
        return responseResult;
    }

    private Boolean addToTask(Integer newsId,Long executeTime){
        Task task = new Task();
        task.setExecuteTime(executeTime);

        WmNews wmNews = new WmNews();
        wmNews.setId(newsId);

        task.setParameters(ProtostuffUtil.serialize(wmNews));

        ResponseResult responseResult = scheduleClient.addTask(task);
        if (responseResult != null && responseResult.getCode()==200){
            return true;
        }
        return false;
    }
    //自动布局方法
    public List<String> autoLayout(List<String> contentImages){
        //从内容图获取图片,填充到封面图上
        int size = contentImages.size();
        ArrayList<String> converImages = new ArrayList<>();

        //判断内容图的长度
        //长度为0 -> 无图
        if (size == 0){
            return converImages;
        }
        //长度为1 -> 单图
        if (size == 1){
            converImages.add(contentImages.get(0));
            return converImages;
        }
        //长度大于3 -> 多图
        if (size > 3){
            converImages.addAll(contentImages.subList(0,2));
            return converImages;
        }
        return contentImages;
    }

    //插入素材和素材关系
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean addMaterial(List<String> images,Integer type,Integer newsId){
        if (CollectionUtils.isEmpty(images)){
            log.warn("素材不能为空");
            return false;
        }

        //遍历图片集合
        for (String image : images) {
            if (StringUtils.isEmpty(image)){
                continue;
            }
            //判断当前图片是否在素材库中有相同的
            LambdaQueryWrapper<WmMaterial> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WmMaterial::getUrl,image);
            WmMaterial wmMaterial = wmMaterialMapper.selectOne(wrapper);

            Integer materialId = null;
            if (wmMaterial == null){
                WmMaterial material = new WmMaterial();
                material.setUserId(WmUserThreadLocal.get().getId());
                material.setUrl(image);
                material.setIsCollection((short) 0);
                material.setType((short) 0);
                material.setCreatedTime(new Date());

                int materialResult = wmMaterialMapper.insert(material);
                if (materialResult < 1){
                    log.warn("素材插入失败");
                    throw new RuntimeException("素材插入失败");
                }
                //如果不存在,插入素材,返回id
                 materialId = material.getId();
            }else {
                //如果不存在,返回id
                materialId = wmMaterial.getUserId();
            }

            //插入关系表
            WmNewsMaterial newsMaterial = new WmNewsMaterial();
            newsMaterial.setMaterialId(materialId);
            newsMaterial.setNewsId(newsId);
            newsMaterial.setType(type.shortValue());
            newsMaterial.setOrd((short) 0);

            int newMaterialResult = wmNewsMaterialMapper.insert(newsMaterial);
            if (newMaterialResult < 1){
                throw new RuntimeException("素材关系插入失败");
            }
        }

        //返回ture
        return true;

    }

    //提取内容图
    public List<String> getContentImages(String content){
        List<Map> maps = JSON.parseArray(content, Map.class);
        if (CollectionUtils.isEmpty(maps)){
            log.warn("内容为空");
            return null;
        }
        ArrayList<String> imageList = new ArrayList<>();

        //遍历集合,保存type为"image"类型的"value"值
        for (Map map : maps) {
            if (CollectionUtils.isEmpty(map)){
                continue;
            }

            if ("image".equals(map.get("type"))){
                try {
                    imageList.add((String)map.get("value"));
                } catch (Exception e) {
                    log.warn("value解析失败");
                    continue;
                }
            }
        }

        return imageList;
    }

    //提取新闻内容
    public WmNews getWmNews(WmNewsDto dto){
        if (dto == null){
            log.warn("dto不能为空");
            return null;
        }
        WmNews wmNews = new WmNews();
        //将dto和wmNews中的相同字段赋值给wmNews
        BeanUtils.copyProperties(dto,wmNews);
        wmNews.setUserId(WmUserThreadLocal.get().getId());

        //处理差异的字段
        if (dto.getType() == -1){
            wmNews.setType(null);
        }

        wmNews.setCreatedTime(new Date());
        List<String> images = dto.getImages();
        //类型转换:List<String> --> String(用,隔开)
        String imagesString = StringUtils.join(images, ",");
        wmNews.setImages(imagesString);
        wmNews.setEnable((short) 1);

        return wmNews;
    }


}
